import axios from 'axios';
import { cloneDeep } from 'lodash';
import { message } from 'antd';
import { history } from 'umi';
import { dispatch } from 'dva';
import { apiPrefix } from './config';
const { parse, compile } = require("path-to-regexp")

window.cancelRequest = new Map();

const REFRESH_TOKEN_API = apiPrefix + '/refresh';

export default async function request(options) {
  let { data, url } = options;
  const cloneData = cloneDeep(data);

  try {
    let domain = '';
    const urlMatch = url.match(/[a-zA-z]+:\/\/[^/]*/);
    if (urlMatch) {
      ;[domain] = urlMatch;
      url = url.slice(domain.length);
    }

    const match = parse(url);
    url = compile(url)(data);

    for (const item of match) {
      if (item instanceof Object && item.name in cloneData) {
        delete cloneData[item.name];
      }
    }
    url = domain + url;
  } catch (e) {
    message.error(e.message);
  }

  options.url = url;

  if (options.method.toUpperCase() === 'GET') {
    options.params = data;
  }

  const accessToken = window.localStorage.getItem('hudazx-blog-accessToken');
  options.headers = { "Authorization": `${accessToken}` };

  // formdata文件处理  
  if (data && data.fileData) {
    data.formFiles = { "files": data.fileData };
    delete data.fileData;
  }
  if (data && data.formFiles) {
    const { formFiles, ...otherData } = data;
    options.headers['Content-type'] = 'multipart/form-data';
    const formData = new FormData();
    Object.entries(formFiles).forEach(([key, files]) => {
      files.forEach(f => {
        formData.append(key, f);
      });
    });
    formData.append('data', JSON.stringify(otherData));
    options.data = formData;
  }

  if (data && data.hasOwnProperty('onUploadProgress')) {
    options.onUploadProgress = data.onUploadProgress;
    delete data.onUploadProgress;
  }

  try {
    const response = await axios(options);
    const { statusText, status, data } = response;

    if (data.code && data.code === 2005) {
      // Token 过期，尝试使用refreshToken获取新token  
      const refreshToken = window.localStorage.getItem('hudazx-blog-refreshToken');
      if (refreshToken) {
        try {
          const refreshResponse = await axios.post(REFRESH_TOKEN_API, { refreshToken });
          const { data: refreshData } = refreshResponse;

          if (refreshData.code === 0) {
            const newAccessToken = refreshData.accessToken;
            window.localStorage.setItem('hudazx-blog-accessToken', newAccessToken);

            // 使用dva的dispatch函数更新user命名空间  
            dispatch({
              type: 'user/updateUser',
              payload: { accessToken: newAccessToken },
            });

            // 重新发起原始请求  
            return request(options);
          } else {
            // 刷新token失败，可能需要重新登录  
            window.localStorage.setItem('accessToken', '');
            dispatch({
              type: 'user/logoutUser',
            })
            history.push({ pathname: '/homePage' });
            message.error('Token refresh failed. Please log in again.');
          }
        } catch (refreshError) {
          // 处理刷新token时的错误  
          window.localStorage.setItem('accessToken', '');
          history.push({ pathname: '/homePage' });
          message.error('Failed to refresh token. Please check your network connection.');
        }
      } else {
        // 没有refreshToken，需要重新登录  
        window.localStorage.setItem('accessToken', '');
        history.push({ pathname: '/homePage' });
      }
    } else {
      // 正常处理响应  
      let result = {};
      if (typeof data === 'object') {
        result = data;
        if (Array.isArray(data)) {
          result.list = data;
        }
      } else {
        result.data = data;
      }

      return Promise.resolve({
        success: true,
        message: statusText,
        statusCode: status,
        ...result,
      });
    }
  } catch (error) {
    // 处理请求错误  
    const { response, message } = error;
    let msg;
    let statusCode;

    if (response && response instanceof Object && response.status !== 0) {
      const { data, statusText } = response;
      statusCode = response.status;
      msg = data.message || statusText;
    } else {
      statusCode = 600;
      msg = error.message || 'Network Error';
    }

    return Promise.reject({
      success: false,
      statusCode,
      message: msg,
    });
  }
}